from src.models.Role import RoleHandleMapping, Role
from src.models.Menu import SysHandle
from src.models.Group import GroupAuth, GroupUser
from flask import Request
from src.util import JwtUtil
from src.service.FileManageService import File, getAuth, FileEntry
from datetime import datetime, timedelta, UTC
from src.service.ConfigManagerService import getConfigKey

__GroupUser = GroupUser()
__GroupAuth = GroupAuth()


# 验证角色是否拥有该路由权限
def authHandleByRid(rids, hid):
    if 1 in rids:
        return True
    rids = Role.getCanUseRoleIdsInId(rids)
    return RoleHandleMapping.hasRolesHandle(rids, hid)


# 验证用户组是否拥有该路由权限
def authHandleByGroup(uid, hid):
    gids = __GroupUser.getUserGroupByUid(uid)
    return __GroupAuth.authentication(gids, 'route', hid)


def interfaceAuth(req: Request):
    # 查询系统是否拥有该接口
    handle: dict = SysHandle.getHandleByPathAndMethod(req.url_rule, req.method)
    # 无该接口放行
    if handle is None:
        return True
    if handle.get('status') != '1':
        return False
    # 登陆验证
    token = req.headers.get("Authorization")
    # 获取用户信息
    info: dict = JwtUtil.authToken(token)
    # 如果是公共接口 放行
    if handle['key'] == 'public':
        return True
    # 身份信息过期
    if not info:
        return None
    # 身份有效保存信息
    req.environ.setdefault("UID", info.get('id'))
    req.environ.setdefault("RID", info.get('rid'))
    req.environ.setdefault("USERNAME", info.get('username'))
    # 如果是用户接口 验证登陆完成直接放行
    if handle['key'] == 'user':
        return True
    # 系统接口需要验证角色权限
    if handle['key'] == 'sys':
        r1 = authHandleByRid([info.get('rid')], handle.get('hId'))
        r2 = authHandleByGroup(info.get('id'), handle.get('hId'))
        return r1 or r2


# 过期检查
def _exceedAuth(item: dict):
    createTime: datetime = item.get('createTime')
    exceedTime = item.get('exceedTime') or 0
    # 验证token 是否过期  0 标识没有设置过期时间
    if exceedTime != 0:
        exceedTime = createTime + timedelta(milliseconds=exceedTime)
        exceedTime = exceedTime.replace(tzinfo=UTC).timestamp()
        # 过期检查 如果过期了就进行下一次循环
        if exceedTime < datetime.now(UTC).timestamp():
            return True
    return False


# 鉴权方式 待优化
# 静态资源权限校验
def staticAuth(req: Request):
    path = req.path.replace("/static/", "")
    file_info = File.getByPath(path)
    if not file_info:
        return True
    file_info = FileEntry(**file_info)
    a_type = req.args.get('auth_type') or 'token'
    # 获取公共访问权限
    auth_list: list[dict] = getAuth(file_info, 'public')
    # auth_list2: list[dict] = []
    # public_list: list[dict] = []
    # for item in auth_list:
    #     if item.get("authType") == 'public':
    #         public_list.append(item)
    #     elif item.get("authType") == a_type:
    #         auth_list2.append(item)
    for item in auth_list:
        # 若是公共访问权限没过期 以及权限是否为读取权限
        if item.get("canRead") == 'Y' and not _exceedAuth(item):
            return True
    # 获取用户使用的权限
    auth_list: list[dict] = getAuth(file_info, a_type)
    # 使用token 方式鉴权
    if a_type == "token":
        for item in auth_list:
            # 检查是否过期 以及权限是否为读取权限
            if item.get("canRead") == 'N' or _exceedAuth(item):
                continue
            # 获取token
            token = req.args.get('token') or req.headers.get("StaticToken") or ""
            if token == item['token']:
                return True
    # 由于一下方式都需要鉴定登陆权限
    token = req.headers.get("Authorization") or req.args.get('Authorization')
    info: dict = JwtUtil.authToken(token)
    # 身份信息过期
    if not info:
        return None
    # 使用用户组方式访问
    if a_type == "group":
        ids: list[int] = list()
        for item in auth_list:
            if item.get("canRead") == 'N' and _exceedAuth(item):
                continue
            ids.append(item.get('objId'))
        # 检查用户组
        if __GroupUser.hasUser(ids, info.get('id')):
            return True
    # 鉴别用户方式
    elif a_type == "user":
        ids: list[int] = list()
        for item in auth_list:
            if item.get("canRead") == 'N' and _exceedAuth(item):
                continue
            ids.append(item.get('objId'))
        # 检查用户组
        if info.get('id') in ids:
            return True
    # 角色方式
    elif a_type == "role":
        ids: list[int] = list()
        for item in auth_list:
            if item.get("canRead") == 'N' and _exceedAuth(item):
                continue
            ids.append(item.get('objId'))
        # 检查用户组
        if info.get('rid') in ids:
            return True
    return False
    # return True


# 设置 平台 密钥
def addPlatformKey():
    key = getConfigKey("##platformKey", 'base')
    if key:
        JwtUtil.setKey(key.get('value'))


addPlatformKey()
